// type_traits standard header (core)
#pragma once
#ifndef _TYPE_TRAITS_
#define _TYPE_TRAITS_
#ifndef RC_INVOKED
#include <xstddef>

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new

#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored

_STD_BEGIN
// STRUCT TEMPLATE integer_sequence
template <class _Ty, _Ty... _Vals>
struct integer_sequence { // sequence of integer parameters
    static_assert(is_integral_v<_Ty>, "integer_sequence<T, I...> requires T to be an integral type.");

    using value_type = _Ty;

    _NODISCARD static constexpr size_t size() noexcept {
        return sizeof...(_Vals);
    }
};

// ALIAS TEMPLATE make_integer_sequence
template <class _Ty, _Ty _Size>
using make_integer_sequence = __make_integer_seq<integer_sequence, _Ty, _Size>;

template <size_t... _Vals>
using index_sequence = integer_sequence<size_t, _Vals...>;

template <size_t _Size>
using make_index_sequence = make_integer_sequence<size_t, _Size>;

template <class... _Types>
using index_sequence_for = make_index_sequence<sizeof...(_Types)>;

// STRUCT TEMPLATE conjunction
template <bool _First_value, class _First, class... _Rest>
struct _Conjunction { // handle false trait or last trait
    using type = _First;
};

template <class _True, class _Next, class... _Rest>
struct _Conjunction<true, _True, _Next, _Rest...> { // the first trait is true, try the next one
    using type = typename _Conjunction<_Next::value, _Next, _Rest...>::type;
};

template <class... _Traits>
struct conjunction : true_type {}; // If _Traits is empty, true_type

template <class _First, class... _Rest>
struct conjunction<_First, _Rest...> : _Conjunction<_First::value, _First, _Rest...>::type {
    // the first false trait in _Traits, or the last trait if none are false
};

template <class... _Traits>
_INLINE_VAR constexpr bool conjunction_v = conjunction<_Traits...>::value;

#if !defined(__EDG__) && !defined(__NVCC__) // TRANSITION, VSO#736632
// STRUCT TEMPLATE disjunction
template <bool _First_value, class _First, class... _Rest>
struct _Disjunction { // handle true trait or last trait
    using type = _First;
};

template <class _False, class _Next, class... _Rest>
struct _Disjunction<false, _False, _Next, _Rest...> { // first trait is false, try the next trait
    using type = typename _Disjunction<_Next::value, _Next, _Rest...>::type;
};

template <class... _Traits>
struct disjunction : false_type {}; // If _Traits is empty, false_type

template <class _First, class... _Rest>
struct disjunction<_First, _Rest...> : _Disjunction<_First::value, _First, _Rest...>::type {
    // the first true trait in _Traits, or the last trait if none are true
};

template <class... _Traits>
_INLINE_VAR constexpr bool disjunction_v = disjunction<_Traits...>::value;
#endif // TRANSITION, VSO#736632

// STRUCT TEMPLATE negation
template <class _Trait>
struct negation : bool_constant<!static_cast<bool>(_Trait::value)> {}; // The negated result of _Trait

template <class _Trait>
_INLINE_VAR constexpr bool negation_v = negation<_Trait>::value;

#if !defined(__EDG__) && !defined(__NVCC__) // TRANSITION, VSO#736632
// VARIABLE TEMPLATE _Is_any_of_v
template <class _Ty, class... _Types>
_INLINE_VAR constexpr bool _Is_any_of_v = disjunction_v<is_same<_Ty, _Types>...>;
#endif // TRANSITION, VSO#736632

// STRUCT TEMPLATE _Arg_types
template <class... _Types>
struct _Arg_types {}; // provide argument_type, etc. (sometimes)

template <class _Ty1>
struct _Arg_types<_Ty1> {
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty1 argument_type;
};

template <class _Ty1, class _Ty2>
struct _Arg_types<_Ty1, _Ty2> {
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty1 first_argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty2 second_argument_type;
};

// STRUCT TEMPLATE is_function
template <class _Ty>
struct _Is_function { // determine whether _Ty is a function
    using _Bool_type = false_type; // NB: members are user-visible via _Weak_types
};

#define _IS_FUNCTION(CALL_OPT, CV_OPT, REF_OPT, NOEXCEPT_OPT)                                           \
    template <class _Ret, class... _Types>                                                              \
    struct _Is_function<_Ret CALL_OPT(_Types...) CV_OPT REF_OPT NOEXCEPT_OPT> : _Arg_types<_Types...> { \
        using _Bool_type = true_type;                                                                   \
        _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret result_type;                                     \
    };

_NON_MEMBER_CALL_CV_REF_NOEXCEPT(_IS_FUNCTION)
#undef _IS_FUNCTION

#define _IS_FUNCTION_ELLIPSIS(CV_REF_NOEXCEPT_OPT)                                                            \
    template <class _Ret, class... _Types>                                                                    \
    struct _Is_function<_Ret(_Types..., ...) CV_REF_NOEXCEPT_OPT> { /* no calling conventions for ellipsis */ \
        using _Bool_type = true_type;                                                                         \
        _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret result_type;                                           \
    };

_CLASS_DEFINE_CV_REF_NOEXCEPT(_IS_FUNCTION_ELLIPSIS)
#undef _IS_FUNCTION_ELLIPSIS

template <class _Ty>
struct is_function : bool_constant<_Is_function<_Ty>::_Bool_type::value> {}; // determine whether _Ty is a function

template <class _Ty>
_INLINE_VAR constexpr bool is_function_v = _Is_function<_Ty>::_Bool_type::value;


template <class _Ty>
struct _Is_memfunptr { // base class for member function pointer predicates
    using _Bool_type = false_type; // NB: members are user-visible via _Weak_types
};

#define _IS_MEMFUNPTR(CALL_OPT, CV_OPT, REF_OPT, NOEXCEPT_OPT)                            \
    template <class _Ret, class _Arg0, class... _Types>                                   \
    struct _Is_memfunptr<_Ret (CALL_OPT _Arg0::*)(_Types...) CV_OPT REF_OPT NOEXCEPT_OPT> \
        : _Arg_types<CV_OPT _Arg0*, _Types...> {                                          \
        using _Bool_type = true_type;                                                     \
        _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret result_type;                       \
        using _Class_type = _Arg0;                                                        \
        using _Guide_type = enable_if<!is_same_v<int REF_OPT, int&&>, _Ret(_Types...)>;   \
    };

_MEMBER_CALL_CV_REF_NOEXCEPT(_IS_MEMFUNPTR)
#undef _IS_MEMFUNPTR

#define _IS_MEMFUNPTR_ELLIPSIS(CV_REF_NOEXCEPT_OPT)                          \
    template <class _Ret, class _Arg0, class... _Types>                      \
    struct _Is_memfunptr<_Ret (_Arg0::*)(_Types..., ...)                     \
            CV_REF_NOEXCEPT_OPT> { /* no calling conventions for ellipsis */ \
        using _Bool_type = true_type;                                        \
        _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret result_type;          \
        using _Class_type = _Arg0;                                           \
        using _Guide_type = enable_if<false>;                                \
    };

_CLASS_DEFINE_CV_REF_NOEXCEPT(_IS_MEMFUNPTR_ELLIPSIS)
#undef _IS_MEMFUNPTR_ELLIPSIS

// STRUCT TEMPLATE is_void
#if defined(__EDG__) || defined(__NVCC__) // TRANSITION, VSO#736632
template <class>
struct is_void : false_type {}; // determine whether type argument is cv-qualified void

template <>
struct is_void<void> : true_type {};

template <>
struct is_void<const void> : true_type {};

template <>
struct is_void<volatile void> : true_type {};

template <>
struct is_void<const volatile void> : true_type {};

template <class _Ty>
_INLINE_VAR constexpr bool is_void_v = is_void<_Ty>::value;
#else // ^^^ workaround / no workaround vvv
template <class>
_INLINE_VAR constexpr bool is_void_v = false; // determine whether type argument is cv-qualified void

template <>
_INLINE_VAR constexpr bool is_void_v<void> = true;

template <>
_INLINE_VAR constexpr bool is_void_v<const void> = true;

template <>
_INLINE_VAR constexpr bool is_void_v<volatile void> = true;

template <>
_INLINE_VAR constexpr bool is_void_v<const volatile void> = true;

template <class _Ty>
struct is_void : bool_constant<is_void_v<_Ty>> {};
#endif // TRANSITION, VSO#736632

// ALIAS TEMPLATE void_t
template <class... _Types>
using void_t = void;

// Type modifiers
// STRUCT TEMPLATE add_const
template <class _Ty>
struct add_const { // add top-level const qualifier
    using type = const _Ty;
};

template <class _Ty>
using add_const_t = typename add_const<_Ty>::type;

// STRUCT TEMPLATE add_volatile
template <class _Ty>
struct add_volatile { // add top-level volatile qualifier
    using type = volatile _Ty;
};

template <class _Ty>
using add_volatile_t = typename add_volatile<_Ty>::type;

// STRUCT TEMPLATE add_cv
template <class _Ty>
struct add_cv { // add top-level const and volatile qualifiers
    using type = const volatile _Ty;
};

template <class _Ty>
using add_cv_t = typename add_cv<_Ty>::type;

// STRUCT TEMPLATE _Add_reference
template <class _Ty, class = void>
struct _Add_reference { // add reference (non-referenceable type)
    using _Lvalue = _Ty;
    using _Rvalue = _Ty;
};

template <class _Ty>
struct _Add_reference<_Ty, void_t<_Ty&>> { // (referenceable type)
    using _Lvalue = _Ty&;
    using _Rvalue = _Ty&&;
};

// STRUCT TEMPLATE add_lvalue_reference
template <class _Ty>
struct add_lvalue_reference {
    using type = typename _Add_reference<_Ty>::_Lvalue;
};

template <class _Ty>
using add_lvalue_reference_t = typename _Add_reference<_Ty>::_Lvalue;

// STRUCT TEMPLATE add_rvalue_reference
template <class _Ty>
struct add_rvalue_reference {
    using type = typename _Add_reference<_Ty>::_Rvalue;
};

template <class _Ty>
using add_rvalue_reference_t = typename _Add_reference<_Ty>::_Rvalue;

// FUNCTION TEMPLATE declval
template <class _Ty>
add_rvalue_reference_t<_Ty> declval() noexcept;

// STRUCT TEMPLATE remove_extent
template <class _Ty>
struct remove_extent { // remove array extent
    using type = _Ty;
};

template <class _Ty, size_t _Ix>
struct remove_extent<_Ty[_Ix]> {
    using type = _Ty;
};

template <class _Ty>
struct remove_extent<_Ty[]> {
    using type = _Ty;
};

template <class _Ty>
using remove_extent_t = typename remove_extent<_Ty>::type;

// STRUCT TEMPLATE remove_all_extents
template <class _Ty>
struct remove_all_extents { // remove all array extents
    using type = _Ty;
};

template <class _Ty, size_t _Ix>
struct remove_all_extents<_Ty[_Ix]> {
    using type = typename remove_all_extents<_Ty>::type;
};

template <class _Ty>
struct remove_all_extents<_Ty[]> {
    using type = typename remove_all_extents<_Ty>::type;
};

template <class _Ty>
using remove_all_extents_t = typename remove_all_extents<_Ty>::type;

// STRUCT TEMPLATE remove_pointer
template <class _Ty>
struct remove_pointer {
    using type = _Ty;
};

template <class _Ty>
struct remove_pointer<_Ty*> {
    using type = _Ty;
};

template <class _Ty>
struct remove_pointer<_Ty* const> {
    using type = _Ty;
};

template <class _Ty>
struct remove_pointer<_Ty* volatile> {
    using type = _Ty;
};


template <class _Ty>
struct remove_pointer<_Ty* const volatile> {
    using type = _Ty;
};

template <class _Ty>
using remove_pointer_t = typename remove_pointer<_Ty>::type;

// STRUCT TEMPLATE add_pointer
template <class _Ty, class = void>
struct _Add_pointer { // add pointer (pointer type cannot be formed)
    using type = _Ty;
};

template <class _Ty>
struct _Add_pointer<_Ty, void_t<remove_reference_t<_Ty>*>> { // (pointer type can be formed)
    using type = remove_reference_t<_Ty>*;
};

template <class _Ty>
struct add_pointer {
    using type = typename _Add_pointer<_Ty>::type;
};

template <class _Ty>
using add_pointer_t = typename _Add_pointer<_Ty>::type;

// TYPE PREDICATES
// STRUCT TEMPLATE is_array
template <class>
_INLINE_VAR constexpr bool is_array_v = false; // determine whether type argument is an array

template <class _Ty, size_t _Nx>
_INLINE_VAR constexpr bool is_array_v<_Ty[_Nx]> = true;

template <class _Ty>
_INLINE_VAR constexpr bool is_array_v<_Ty[]> = true;

template <class _Ty>
struct is_array : bool_constant<is_array_v<_Ty>> {};

// STRUCT TEMPLATE is_lvalue_reference
template <class>
_INLINE_VAR constexpr bool is_lvalue_reference_v = false; // determine whether type argument is an lvalue reference

template <class _Ty>
_INLINE_VAR constexpr bool is_lvalue_reference_v<_Ty&> = true;

template <class _Ty>
struct is_lvalue_reference : bool_constant<is_lvalue_reference_v<_Ty>> {};

// STRUCT TEMPLATE is_rvalue_reference
template <class>
_INLINE_VAR constexpr bool is_rvalue_reference_v = false; // determine whether type argument is an rvalue reference

template <class _Ty>
_INLINE_VAR constexpr bool is_rvalue_reference_v<_Ty&&> = true;

template <class _Ty>
struct is_rvalue_reference : bool_constant<is_rvalue_reference_v<_Ty>> {};

// STRUCT TEMPLATE is_reference
template <class>
_INLINE_VAR constexpr bool is_reference_v = false; // determine whether type argument is a reference

template <class _Ty>
_INLINE_VAR constexpr bool is_reference_v<_Ty&> = true;

template <class _Ty>
_INLINE_VAR constexpr bool is_reference_v<_Ty&&> = true;

template <class _Ty>
struct is_reference : bool_constant<is_reference_v<_Ty>> {};

// STRUCT TEMPLATE is_member_object_pointer
template <class _Ty, bool _Pmf = _Is_memfunptr<_Ty>::_Bool_type::value>
struct _Is_member_object_pointer { // determine whether _Ty is a pointer to member object
    static constexpr bool value = false;
};

template <class _Ty1, class _Ty2>
struct _Is_member_object_pointer<_Ty1 _Ty2::*, false> {
    static constexpr bool value = true;
    using _Class_type           = _Ty2;
};

template <class _Ty>
_INLINE_VAR constexpr bool is_member_object_pointer_v = // determine whether _Ty is a pointer to member object
    _Is_member_object_pointer<remove_cv_t<_Ty>>::value;

template <class _Ty>
struct is_member_object_pointer : bool_constant<is_member_object_pointer_v<_Ty>> {};

// STRUCT TEMPLATE is_member_function_pointer
template <class _Ty>
_INLINE_VAR constexpr bool is_member_function_pointer_v = // determine whether _Ty is a pointer to member function
    _Is_memfunptr<remove_cv_t<_Ty>>::_Bool_type::value;

template <class _Ty>
struct is_member_function_pointer : bool_constant<is_member_function_pointer_v<_Ty>> {};

// STRUCT TEMPLATE is_pointer
template <class>
_INLINE_VAR constexpr bool is_pointer_v = false; // determine whether _Ty is a pointer

template <class _Ty>
_INLINE_VAR constexpr bool is_pointer_v<_Ty*> = true;

template <class _Ty>
_INLINE_VAR constexpr bool is_pointer_v<_Ty* const> = true;

template <class _Ty>
_INLINE_VAR constexpr bool is_pointer_v<_Ty* volatile> = true;

template <class _Ty>
_INLINE_VAR constexpr bool is_pointer_v<_Ty* const volatile> = true;

template <class _Ty>
struct is_pointer : bool_constant<is_pointer_v<_Ty>> {};

// STRUCT TEMPLATE is_null_pointer
template <class _Ty>
_INLINE_VAR constexpr bool is_null_pointer_v =
    is_same_v<remove_cv_t<_Ty>, nullptr_t>; // determine whether _Ty is cv-qualified nullptr_t

template <class _Ty>
struct is_null_pointer : bool_constant<is_null_pointer_v<_Ty>> {};

// STRUCT TEMPLATE is_union
template <class _Ty>
struct is_union : bool_constant<__is_union(_Ty)> {}; // determine whether _Ty is a union

template <class _Ty>
_INLINE_VAR constexpr bool is_union_v = __is_union(_Ty);

// STRUCT TEMPLATE is_class
template <class _Ty>
struct is_class : bool_constant<__is_class(_Ty)> {}; // determine whether _Ty is a class

template <class _Ty>
_INLINE_VAR constexpr bool is_class_v = __is_class(_Ty);

// STRUCT TEMPLATE is_fundamental
template <class _Ty>
_INLINE_VAR constexpr bool is_fundamental_v = is_arithmetic_v<_Ty> || is_void_v<_Ty> || is_null_pointer_v<_Ty>;

template <class _Ty>
struct is_fundamental : bool_constant<is_fundamental_v<_Ty>> {}; // determine whether _Ty is a fundamental type

// STRUCT TEMPLATE is_object
template <class _Ty>
_INLINE_VAR constexpr bool is_object_v = !is_function_v<_Ty> && !is_reference_v<_Ty> && !is_void_v<_Ty>;

template <class _Ty>
struct is_object : bool_constant<is_object_v<_Ty>> {}; // determine whether _Ty is an object type

// STRUCT TEMPLATE is_convertible
template <class _From, class _To>
struct is_convertible : bool_constant<__is_convertible_to(_From, _To)> {
    // determine whether _From is convertible to _To
};

template <class _From, class _To>
_INLINE_VAR constexpr bool is_convertible_v = __is_convertible_to(_From, _To);

// STRUCT TEMPLATE is_enum
template <class _Ty>
struct is_enum : bool_constant<__is_enum(_Ty)> {}; // determine whether _Ty is an enumerated type

template <class _Ty>
_INLINE_VAR constexpr bool is_enum_v = __is_enum(_Ty);

// STRUCT TEMPLATE is_compound
template <class _Ty>
struct is_compound : bool_constant<!is_fundamental_v<_Ty>> {}; // determine whether _Ty is a compound type

template <class _Ty>
_INLINE_VAR constexpr bool is_compound_v = !is_fundamental_v<_Ty>;

// STRUCT TEMPLATE is_member_pointer
template <class _Ty>
_INLINE_VAR constexpr bool is_member_pointer_v = is_member_object_pointer_v<_Ty> || is_member_function_pointer_v<_Ty>;

template <class _Ty>
struct is_member_pointer : bool_constant<is_member_pointer_v<_Ty>> {}; // determine whether _Ty is a pointer to member

// STRUCT TEMPLATE is_scalar
template <class _Ty>
_INLINE_VAR constexpr bool is_scalar_v = // determine whether _Ty is a scalar type
    is_arithmetic_v<_Ty> || is_enum_v<_Ty> || is_pointer_v<_Ty> || is_member_pointer_v<_Ty> || is_null_pointer_v<_Ty>;

template <class _Ty>
struct is_scalar : bool_constant<is_scalar_v<_Ty>> {};

// STRUCT TEMPLATE is_const
template <class>
_INLINE_VAR constexpr bool is_const_v = false; // determine whether type argument is const qualified

template <class _Ty>
_INLINE_VAR constexpr bool is_const_v<const _Ty> = true;

template <class _Ty>
struct is_const : bool_constant<is_const_v<_Ty>> {};

// STRUCT TEMPLATE is_volatile
template <class>
_INLINE_VAR constexpr bool is_volatile_v = false; // determine whether type argument is volatile qualified

template <class _Ty>
_INLINE_VAR constexpr bool is_volatile_v<volatile _Ty> = true;

template <class _Ty>
struct is_volatile : bool_constant<is_volatile_v<_Ty>> {};

// STRUCT TEMPLATE is_pod
template <class _Ty>
struct is_pod : bool_constant<__is_pod(_Ty)> {}; // determine whether _Ty is a POD type

template <class _Ty>
_INLINE_VAR constexpr bool is_pod_v = __is_pod(_Ty);

// STRUCT TEMPLATE is_empty
template <class _Ty>
struct is_empty : bool_constant<__is_empty(_Ty)> {}; // determine whether _Ty is an empty class

template <class _Ty>
_INLINE_VAR constexpr bool is_empty_v = __is_empty(_Ty);

// STRUCT TEMPLATE is_polymorphic
template <class _Ty>
struct is_polymorphic : bool_constant<__is_polymorphic(_Ty)> {}; // determine whether _Ty is a polymorphic type

template <class _Ty>
_INLINE_VAR constexpr bool is_polymorphic_v = __is_polymorphic(_Ty);

// STRUCT TEMPLATE is_abstract
template <class _Ty>
struct is_abstract : bool_constant<__is_abstract(_Ty)> {}; // determine whether _Ty is an abstract class

template <class _Ty>
_INLINE_VAR constexpr bool is_abstract_v = __is_abstract(_Ty);

// STRUCT TEMPLATE is_final
template <class _Ty>
struct is_final : bool_constant<__is_final(_Ty)> {}; // determine whether _Ty is a final class

template <class _Ty>
_INLINE_VAR constexpr bool is_final_v = __is_final(_Ty);

// STRUCT TEMPLATE is_standard_layout
template <class _Ty>
struct is_standard_layout : bool_constant<__is_standard_layout(_Ty)> {}; // determine whether _Ty is standard layout

template <class _Ty>
_INLINE_VAR constexpr bool is_standard_layout_v = __is_standard_layout(_Ty);

// STRUCT TEMPLATE is_literal_type
template <class _Ty>
struct _CXX17_DEPRECATE_IS_LITERAL_TYPE is_literal_type : bool_constant<__is_literal_type(_Ty)> {
    // determine whether _Ty is a literal type
};

template <class _Ty>
_CXX17_DEPRECATE_IS_LITERAL_TYPE _INLINE_VAR constexpr bool is_literal_type_v = __is_literal_type(_Ty);

// STRUCT TEMPLATE is_trivial
template <class _Ty>
struct is_trivial : bool_constant<__is_trivial(_Ty)> {}; // determine whether _Ty is a trivial type

template <class _Ty>
_INLINE_VAR constexpr bool is_trivial_v = __is_trivial(_Ty);

// STRUCT TEMPLATE is_trivially_copyable
template <class _Ty>
struct is_trivially_copyable : bool_constant<__is_trivially_copyable(_Ty)> {
    // determine whether _Ty is a trivially copyable type
};

template <class _Ty>
_INLINE_VAR constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Ty);

// STRUCT TEMPLATE has_virtual_destructor
template <class _Ty>
struct has_virtual_destructor : bool_constant<__has_virtual_destructor(_Ty)> {
    // determine whether _Ty has a virtual destructor
};

template <class _Ty>
_INLINE_VAR constexpr bool has_virtual_destructor_v = __has_virtual_destructor(_Ty);

#if _HAS_CXX17
// STRUCT TEMPLATE has_unique_object_representations
template <class _Ty>
struct has_unique_object_representations : bool_constant<__has_unique_object_representations(_Ty)> {
    // determine whether _Ty has unique object representations
};

template <class _Ty>
_INLINE_VAR constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Ty);

// STRUCT TEMPLATE is_aggregate
template <class _Ty>
struct is_aggregate : bool_constant<__is_aggregate(_Ty)> {}; // determine whether _Ty is an aggregate

template <class _Ty>
_INLINE_VAR constexpr bool is_aggregate_v = __is_aggregate(_Ty);
#endif // _HAS_CXX17

// CONSTRUCTIBLE/ASSIGNABLE TRAITS
// STRUCT TEMPLATE is_constructible
template <class _Ty, class... _Args>
struct is_constructible : bool_constant<__is_constructible(_Ty, _Args...)> {
    // determine whether _Ty can be direct-initialized with _Args...
};

template <class _Ty, class... _Args>
_INLINE_VAR constexpr bool is_constructible_v = __is_constructible(_Ty, _Args...);

// STRUCT TEMPLATE is_copy_constructible
template <class _Ty>
struct is_copy_constructible : bool_constant<__is_constructible(_Ty, add_lvalue_reference_t<const _Ty>)> {
    // determine whether _Ty can be direct-initialized with an lvalue const _Ty
};

template <class _Ty>
_INLINE_VAR constexpr bool is_copy_constructible_v = __is_constructible(_Ty, add_lvalue_reference_t<const _Ty>);

// STRUCT TEMPLATE is_default_constructible
template <class _Ty>
struct is_default_constructible : bool_constant<__is_constructible(_Ty)> {
    // determine whether _Ty can be value-initialized
};

template <class _Ty>
_INLINE_VAR constexpr bool is_default_constructible_v = __is_constructible(_Ty);

// STRUCT TEMPLATE _Is_implicitly_default_constructible
template <class _Ty, class = void>
struct _Is_implicitly_default_constructible : false_type {
    // determine whether _Ty can be copy-initialized with {}
};

template <class _Ty>
void _Implicitly_default_construct(const _Ty&);

template <class _Ty>
struct _Is_implicitly_default_constructible<_Ty, void_t<decltype(_Implicitly_default_construct<_Ty>({}))>> : true_type {
};

// STRUCT TEMPLATE is_move_constructible
template <class _Ty>
struct is_move_constructible : bool_constant<__is_constructible(_Ty, _Ty)> {
    // determine whether _Ty can be direct-initialized from an rvalue _Ty
};

template <class _Ty>
_INLINE_VAR constexpr bool is_move_constructible_v = __is_constructible(_Ty, _Ty);

// STRUCT TEMPLATE is_assignable
template <class _To, class _From>
struct is_assignable : bool_constant<__is_assignable(_To, _From)> {}; // determine whether _From can be assigned to _To

template <class _To, class _From>
_INLINE_VAR constexpr bool is_assignable_v = __is_assignable(_To, _From);

// STRUCT TEMPLATE is_copy_assignable
template <class _Ty>
struct is_copy_assignable
    : bool_constant<__is_assignable(add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>)> {
    // determine whether an lvalue const _Ty can be assigned to an lvalue _Ty
};

template <class _Ty>
_INLINE_VAR constexpr bool is_copy_assignable_v = __is_assignable(
    add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>);

#if defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__NVCC__)
template <class _Ty>
struct _Is_copy_assignable_no_precondition_check
    : bool_constant<__is_assignable_no_precondition_check(
          add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>)> {};

template <class _Ty>
_INLINE_VAR constexpr bool _Is_copy_assignable_unchecked_v = __is_assignable_no_precondition_check(
    add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>);
#else // ^^^ Use intrinsic / intrinsic not supported vvv
template <class _Ty>
using _Is_copy_assignable_no_precondition_check = is_copy_assignable<_Ty>;

template <class _Ty>
_INLINE_VAR constexpr bool _Is_copy_assignable_unchecked_v = is_copy_assignable_v<_Ty>;
#endif // defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__NVCC__)

// STRUCT TEMPLATE is_move_assignable
template <class _Ty>
struct is_move_assignable : bool_constant<__is_assignable(add_lvalue_reference_t<_Ty>, _Ty)> {
    // determine whether an rvalue _Ty can be assigned to an lvalue _Ty
};

template <class _Ty>
_INLINE_VAR constexpr bool is_move_assignable_v = __is_assignable(add_lvalue_reference_t<_Ty>, _Ty);

#if defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__NVCC__)
template <class _Ty>
struct _Is_move_assignable_no_precondition_check
    : bool_constant<__is_assignable_no_precondition_check(add_lvalue_reference_t<_Ty>, _Ty)> {};

template <class _Ty>
_INLINE_VAR constexpr bool _Is_move_assignable_unchecked_v = __is_assignable_no_precondition_check(
    add_lvalue_reference_t<_Ty>, _Ty);
#else // ^^^ Use intrinsic / intrinsic not supported vvv
template <class _Ty>
using _Is_move_assignable_no_precondition_check = is_move_assignable<_Ty>;

template <class _Ty>
_INLINE_VAR constexpr bool _Is_move_assignable_unchecked_v = is_move_assignable_v<_Ty>;
#endif // defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__NVCC__)

// STRUCT TEMPLATE is_destructible
template <class _Ty>
struct is_destructible : bool_constant<__is_destructible(_Ty)> {
    // true iff remove_all_extents_t<_Ty> is a reference type, or can be explicitly destroyed
};

template <class _Ty>
_INLINE_VAR constexpr bool is_destructible_v = __is_destructible(_Ty);

// TRIVIAL TRAITS
// STRUCT TEMPLATE is_trivially_constructible
template <class _Ty, class... _Args>
struct is_trivially_constructible : bool_constant<__is_trivially_constructible(_Ty, _Args...)> {
    // determine whether direct-initialization of _Ty with _Args... is trivial
};

template <class _Ty, class... _Args>
_INLINE_VAR constexpr bool is_trivially_constructible_v = __is_trivially_constructible(_Ty, _Args...);

// STRUCT TEMPLATE is_trivially_copy_constructible
template <class _Ty>
struct is_trivially_copy_constructible
    : bool_constant<__is_trivially_constructible(_Ty, add_lvalue_reference_t<const _Ty>)> {
    // determine whether direct-initialization of _Ty with an lvalue const _Ty is trivial
};

template <class _Ty>
_INLINE_VAR constexpr bool is_trivially_copy_constructible_v = __is_trivially_constructible(
    _Ty, add_lvalue_reference_t<const _Ty>);

// STRUCT TEMPLATE is_trivially_default_constructible
template <class _Ty>
struct is_trivially_default_constructible : bool_constant<__is_trivially_constructible(_Ty)> {
    // determine whether value-initialization of _Ty is trivial
};

template <class _Ty>
_INLINE_VAR constexpr bool is_trivially_default_constructible_v = __is_trivially_constructible(_Ty);

// STRUCT TEMPLATE is_trivially_move_constructible
template <class _Ty>
struct is_trivially_move_constructible : bool_constant<__is_trivially_constructible(_Ty, _Ty)> {
    // determine whether direct-initialization of _Ty with an rvalue _Ty is trivial
};

template <class _Ty>
_INLINE_VAR constexpr bool is_trivially_move_constructible_v = __is_trivially_constructible(_Ty, _Ty);

// STRUCT TEMPLATE is_trivially_assignable
template <class _To, class _From>
struct is_trivially_assignable : bool_constant<__is_trivially_assignable(_To, _From)> {
    // determine whether _From can be trivially assigned to _To
};

template <class _To, class _From>
_INLINE_VAR constexpr bool is_trivially_assignable_v = __is_trivially_assignable(_To, _From);

// STRUCT TEMPLATE is_trivially_copy_assignable
template <class _Ty>
struct is_trivially_copy_assignable
    : bool_constant<__is_trivially_assignable(add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>)> {
    // determine whether an lvalue const _Ty can be trivially assigned to an lvalue _Ty
};

template <class _Ty>
_INLINE_VAR constexpr bool is_trivially_copy_assignable_v = __is_trivially_assignable(
    add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>);

// STRUCT TEMPLATE is_trivially_move_assignable
template <class _Ty>
struct is_trivially_move_assignable : bool_constant<__is_trivially_assignable(add_lvalue_reference_t<_Ty>, _Ty)> {
    // determine whether an rvalue _Ty can be trivially assigned to an lvalue _Ty
};

template <class _Ty>
_INLINE_VAR constexpr bool is_trivially_move_assignable_v = __is_trivially_assignable(add_lvalue_reference_t<_Ty>, _Ty);

// STRUCT TEMPLATE is_trivially_destructible
template <class _Ty>
struct is_trivially_destructible : bool_constant<__is_trivially_destructible(_Ty)> {
    // determine whether remove_all_extents_t<_Ty> is a reference type or can trivially be explicitly destroyed
};

template <class _Ty>
_INLINE_VAR constexpr bool is_trivially_destructible_v = __is_trivially_destructible(_Ty);

// NOTHROW TRAITS
// STRUCT TEMPLATE is_nothrow_constructible
template <class _Ty, class... _Args>
struct is_nothrow_constructible : bool_constant<__is_nothrow_constructible(_Ty, _Args...)> {
    // determine whether direct-initialization of _Ty from _Args... is both valid and not potentially-throwing
};

template <class _Ty, class... _Args>
_INLINE_VAR constexpr bool is_nothrow_constructible_v = __is_nothrow_constructible(_Ty, _Args...);

// STRUCT TEMPLATE is_nothrow_copy_constructible
template <class _Ty>
struct is_nothrow_copy_constructible
    : bool_constant<__is_nothrow_constructible(_Ty, add_lvalue_reference_t<const _Ty>)> {
    // determine whether direct-initialization of _Ty from an lvalue const _Ty is both valid
    // and not potentially-throwing
};

template <class _Ty>
_INLINE_VAR constexpr bool is_nothrow_copy_constructible_v = __is_nothrow_constructible(
    _Ty, add_lvalue_reference_t<const _Ty>);

// STRUCT TEMPLATE is_nothrow_default_constructible
template <class _Ty>
struct is_nothrow_default_constructible : bool_constant<__is_nothrow_constructible(_Ty)> {
    // determine whether value-initialization of _Ty is both valid and not potentially-throwing
};

template <class _Ty>
_INLINE_VAR constexpr bool is_nothrow_default_constructible_v = __is_nothrow_constructible(_Ty);

// STRUCT TEMPLATE is_nothrow_move_constructible
template <class _Ty>
struct is_nothrow_move_constructible : bool_constant<__is_nothrow_constructible(_Ty, _Ty)> {
    // determine whether direct-initialization of _Ty from an rvalue _Ty is both valid and not potentially-throwing
};

template <class _Ty>
_INLINE_VAR constexpr bool is_nothrow_move_constructible_v = __is_nothrow_constructible(_Ty, _Ty);

// STRUCT TEMPLATE is_nothrow_assignable
template <class _To, class _From>
struct is_nothrow_assignable : bool_constant<__is_nothrow_assignable(_To, _From)> {
    // determine whether assignment of _From to _To is both valid and not potentially-throwing
};

template <class _To, class _From>
_INLINE_VAR constexpr bool is_nothrow_assignable_v = __is_nothrow_assignable(_To, _From);

// STRUCT TEMPLATE is_nothrow_copy_assignable
template <class _Ty>
struct is_nothrow_copy_assignable
    : bool_constant<__is_nothrow_assignable(add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>)> {
    // determine whether assignment of an lvalue const _Ty to an lvalue _Ty is both valid and not potentially-throwing
};

template <class _Ty>
_INLINE_VAR constexpr bool is_nothrow_copy_assignable_v = __is_nothrow_assignable(
    add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>);

// STRUCT TEMPLATE is_nothrow_move_assignable
template <class _Ty>
struct is_nothrow_move_assignable : bool_constant<__is_nothrow_assignable(add_lvalue_reference_t<_Ty>, _Ty)> {
    // determine whether assignment of an rvalue _Ty to an lvalue _Ty is both valid and not potentially-throwing
};

template <class _Ty>
_INLINE_VAR constexpr bool is_nothrow_move_assignable_v = __is_nothrow_assignable(add_lvalue_reference_t<_Ty>, _Ty);

// STRUCT TEMPLATE is_nothrow_destructible
template <class _Ty>
struct is_nothrow_destructible : bool_constant<__is_nothrow_destructible(_Ty)> {
    // determine whether remove_all_extents_t<_Ty> is a reference type or has
    // non-potentially-throwing explicit destruction
};

template <class _Ty>
_INLINE_VAR constexpr bool is_nothrow_destructible_v = __is_nothrow_destructible(_Ty);

// STRUCT TEMPLATE is_signed
template <class _Ty, bool = is_integral_v<_Ty>>
struct _Sign_base { // determine whether integral type _Ty is signed or unsigned
    using _Uty = remove_cv_t<_Ty>;

    static constexpr bool _Signed   = _Uty(-1) < _Uty(0);
    static constexpr bool _Unsigned = !_Signed;
};

template <class _Ty>
struct _Sign_base<_Ty, false> { // floating-point _Ty is signed
                                // non-arithmetic _Ty is neither signed nor unsigned
    static constexpr bool _Signed   = is_floating_point_v<_Ty>;
    static constexpr bool _Unsigned = false;
};

template <class _Ty>
struct is_signed : bool_constant<_Sign_base<_Ty>::_Signed> {}; // determine whether _Ty is a signed type

template <class _Ty>
_INLINE_VAR constexpr bool is_signed_v = _Sign_base<_Ty>::_Signed;

// STRUCT TEMPLATE is_unsigned
template <class _Ty>
struct is_unsigned : bool_constant<_Sign_base<_Ty>::_Unsigned> {}; // determine whether _Ty is an unsigned type

template <class _Ty>
_INLINE_VAR constexpr bool is_unsigned_v = _Sign_base<_Ty>::_Unsigned;

// VARIABLE TEMPLATE _Is_nonbool_integral
template <class _Ty>
_INLINE_VAR constexpr bool _Is_nonbool_integral = is_integral_v<_Ty> && !is_same_v<remove_cv_t<_Ty>, bool>;

// STRUCT TEMPLATE make_signed
template <bool>
struct _Select { // Select between aliases that extract either their first or second parameter
    template <class _Ty1, class>
    using _Apply = _Ty1;
};

template <>
struct _Select<false> {
    template <class, class _Ty2>
    using _Apply = _Ty2;
};

template <size_t>
struct _Make_signed2; // Choose make_signed strategy by type size

template <>
struct _Make_signed2<1> {
    template <class>
    using _Apply = signed char;
};

template <>
struct _Make_signed2<2> {
    template <class>
    using _Apply = short;
};

template <>
struct _Make_signed2<4> {
    template <class _Ty>
    using _Apply = // assumes LLP64
        typename _Select<is_same_v<_Ty, long> || is_same_v<_Ty, unsigned long>>::template _Apply<long, int>;
};

template <>
struct _Make_signed2<8> {
    template <class>
    using _Apply = long long;
};

template <class _Ty>
using _Make_signed1 = // signed partner to cv-unqualified _Ty
    typename _Make_signed2<sizeof(_Ty)>::template _Apply<_Ty>;

template <class _Ty>
struct make_signed { // signed partner to _Ty
    static_assert(_Is_nonbool_integral<_Ty> || is_enum_v<_Ty>,
        "make_signed<T> requires that T shall be a (possibly cv-qualified) "
        "integral type or enumeration but not a bool type.");

    using type = typename remove_cv<_Ty>::template _Apply<_Make_signed1>;
};

template <class _Ty>
using make_signed_t = typename make_signed<_Ty>::type;

// STRUCT TEMPLATE make_unsigned
template <size_t>
struct _Make_unsigned2; // Choose make_unsigned strategy by type size

template <>
struct _Make_unsigned2<1> {
    template <class>
    using _Apply = unsigned char;
};

template <>
struct _Make_unsigned2<2> {
    template <class>
    using _Apply = unsigned short;
};

template <>
struct _Make_unsigned2<4> {
    template <class _Ty>
    using _Apply = // assumes LLP64
        typename _Select<is_same_v<_Ty, long> || is_same_v<_Ty, unsigned long>>::template _Apply<unsigned long,
            unsigned int>;
};

template <>
struct _Make_unsigned2<8> {
    template <class>
    using _Apply = unsigned long long;
};

template <class _Ty>
using _Make_unsigned1 = // unsigned partner to cv-unqualified _Ty
    typename _Make_unsigned2<sizeof(_Ty)>::template _Apply<_Ty>;

template <class _Ty>
struct make_unsigned { // unsigned partner to _Ty
    static_assert(_Is_nonbool_integral<_Ty> || is_enum_v<_Ty>,
        "make_unsigned<T> requires that T shall be a (possibly cv-qualified) "
        "integral type or enumeration but not a bool type.");

    using type = typename remove_cv<_Ty>::template _Apply<_Make_unsigned1>;
};

template <class _Ty>
using make_unsigned_t = typename make_unsigned<_Ty>::type;

// FUNCTION TEMPLATE _Unsigned_value
template <class _Rep>
constexpr make_unsigned_t<_Rep> _Unsigned_value(_Rep _Val) { // makes _Val unsigned
    return static_cast<make_unsigned_t<_Rep>>(_Val);
}

// STRUCT TEMPLATE alignment_of
template <class _Ty>
struct alignment_of : integral_constant<size_t, alignof(_Ty)> {}; // determine alignment of _Ty

template <class _Ty>
_INLINE_VAR constexpr size_t alignment_of_v = alignof(_Ty);

// STRUCT TEMPLATE aligned_storage
#define _FITS(_Ty) _Align <= alignof(_Ty)
#define _NEXT_ALIGN(_Ty) using type = typename _Aligned<_Len, _Align, _Ty, _FITS(_Ty)>::type

template <class _Ty, size_t _Len>
union _Align_type { // union with size _Len bytes and alignment of _Ty
    _Ty _Val;
    char _Pad[_Len];
};

template <size_t _Len, size_t _Align, class _Ty, bool _Ok>
struct _Aligned; // define type with size _Len and alignment _Ty

template <size_t _Len, size_t _Align, class _Ty>
struct _Aligned<_Len, _Align, _Ty, true> {
    using type = _Align_type<_Ty, _Len>;
};

template <size_t _Len, size_t _Align>
struct _Aligned<_Len, _Align, double, false> {
#ifdef _ENABLE_EXTENDED_ALIGNED_STORAGE
    struct type {
        alignas(_Align) char _Space[_Len];
    };
#else // ^^^ _ENABLE_EXTENDED_ALIGNED_STORAGE / !_ENABLE_EXTENDED_ALIGNED_STORAGE vvv
#ifndef _DISABLE_EXTENDED_ALIGNED_STORAGE
    static_assert(_Always_false<_Aligned>,
        "You've instantiated std::aligned_storage<Len, Align> with an extended alignment (in other "
        "words, Align > alignof(max_align_t)). Before VS 2017 15.8, the member \"type\" would "
        "non-conformingly have an alignment of only alignof(max_align_t). VS 2017 15.8 was fixed to "
        "handle this correctly, but the fix inherently changes layout and breaks binary compatibility "
        "(*only* for uses of aligned_storage with extended alignments). "
        "Please define either "
        "(1) _ENABLE_EXTENDED_ALIGNED_STORAGE to acknowledge that you understand this message and "
        "that you actually want a type with an extended alignment, or "
        "(2) _DISABLE_EXTENDED_ALIGNED_STORAGE to silence this message and get the old non-conformant "
        "behavior.");
#endif // !_DISABLE_EXTENDED_ALIGNED_STORAGE
    using type = _Align_type<max_align_t, _Len>;
#endif // _ENABLE_EXTENDED_ALIGNED_STORAGE
};

template <size_t _Len, size_t _Align>
struct _Aligned<_Len, _Align, int, false> {
    _NEXT_ALIGN(double);
};

template <size_t _Len, size_t _Align>
struct _Aligned<_Len, _Align, short, false> {
    _NEXT_ALIGN(int);
};

template <size_t _Len, size_t _Align>
struct _Aligned<_Len, _Align, char, false> {
    _NEXT_ALIGN(short);
};

template <size_t _Len, size_t _Align = alignof(max_align_t)>
struct aligned_storage { // define type with size _Len and alignment _Align
    using type = typename _Aligned<_Len, _Align, char, _FITS(char)>::type;
};

#undef _FITS
#undef _NEXT_ALIGN

template <size_t _Len, size_t _Align = alignof(max_align_t)>
using aligned_storage_t = typename aligned_storage<_Len, _Align>::type;

// STRUCT TEMPLATE aligned_union
template <size_t... _Vals>
struct _Maximum;

template <>
struct _Maximum<> : integral_constant<size_t, 0> {}; // maximum of nothing is 0

template <size_t _Val>
struct _Maximum<_Val> : integral_constant<size_t, _Val> {}; // maximum of _Val is _Val

template <size_t _First, size_t _Second, size_t... _Rest>
struct _Maximum<_First, _Second, _Rest...> : _Maximum<(_First < _Second ? _Second : _First), _Rest...>::type {
    // find maximum value in _First, _Second, _Rest...
};

template <size_t _Len, class... _Types>
struct aligned_union { // define type with size at least _Len, for storing anything in _Types
    static constexpr size_t _Max_len        = _Maximum<_Len, sizeof(_Types)...>::value; // NOT sizeof...(_Types)
    static constexpr size_t alignment_value = _Maximum<alignof(_Types)...>::value;

    using type = aligned_storage_t<_Max_len, alignment_value>;
};

template <size_t _Len, class... _Types>
using aligned_union_t = typename aligned_union<_Len, _Types...>::type;

// STRUCT TEMPLATE underlying_type
template <class _Ty>
struct underlying_type { // determine underlying type for enum
    using type = __underlying_type(_Ty);
};

template <class _Ty>
using underlying_type_t = typename underlying_type<_Ty>::type;

// STRUCT TEMPLATE rank
template <class _Ty>
_INLINE_VAR constexpr size_t rank_v = 0; // determine number of dimensions of array _Ty

template <class _Ty, size_t _Nx>
_INLINE_VAR constexpr size_t rank_v<_Ty[_Nx]> = rank_v<_Ty> + 1;

template <class _Ty>
_INLINE_VAR constexpr size_t rank_v<_Ty[]> = rank_v<_Ty> + 1;

template <class _Ty>
struct rank : integral_constant<size_t, rank_v<_Ty>> {};

// STRUCT TEMPLATE extent
template <class _Ty, unsigned int _Ix = 0>
_INLINE_VAR constexpr size_t extent_v = 0; // determine extent of dimension _Ix of array _Ty

template <class _Ty, size_t _Nx>
_INLINE_VAR constexpr size_t extent_v<_Ty[_Nx], 0> = _Nx;

template <class _Ty, unsigned int _Ix, size_t _Nx>
_INLINE_VAR constexpr size_t extent_v<_Ty[_Nx], _Ix> = extent_v<_Ty, _Ix - 1>;

template <class _Ty, unsigned int _Ix>
_INLINE_VAR constexpr size_t extent_v<_Ty[], _Ix> = extent_v<_Ty, _Ix - 1>;

template <class _Ty, unsigned int _Ix = 0>
struct extent : integral_constant<size_t, extent_v<_Ty, _Ix>> {};

// STRUCT TEMPLATE is_base_of
template <class _Base, class _Derived>
struct is_base_of : bool_constant<__is_base_of(_Base, _Derived)> {
    // determine whether _Base is a base of or the same as _Derived
};

template <class _Base, class _Derived>
_INLINE_VAR constexpr bool is_base_of_v = __is_base_of(_Base, _Derived);

// STRUCT TEMPLATE decay
template <class _Ty>
struct decay { // determines decayed version of _Ty
    using _Ty1 = remove_reference_t<_Ty>;
    using _Ty2 = typename _Select<is_function_v<_Ty1>>::template _Apply<add_pointer<_Ty1>, remove_cv<_Ty1>>;
    using type = typename _Select<is_array_v<_Ty1>>::template _Apply<add_pointer<remove_extent_t<_Ty1>>, _Ty2>::type;
};

template <class _Ty>
using decay_t = typename decay<_Ty>::type;

// STRUCT TEMPLATE common_type
template <class _Ty1, class _Ty2, class = void>
struct _Decayed_cond_oper {};

template <class _Ty1, class _Ty2>
struct _Decayed_cond_oper<_Ty1, _Ty2, void_t<decltype(false ? _STD declval<_Ty1>() : _STD declval<_Ty2>())>> {
    using type = decay_t<decltype(false ? _STD declval<_Ty1>() : _STD declval<_Ty2>())>;
};

template <class... _Ty>
struct common_type;

template <class... _Ty>
using common_type_t = typename common_type<_Ty...>::type;

template <>
struct common_type<> {};

template <class _Ty1>
struct common_type<_Ty1> : common_type<_Ty1, _Ty1> {};

template <class _Ty1, class _Ty2, class _Decayed1 = decay_t<_Ty1>, class _Decayed2 = decay_t<_Ty2>>
struct _Common_type2 : common_type<_Decayed1, _Decayed2> {};

template <class _Ty1, class _Ty2>
struct _Common_type2<_Ty1, _Ty2, _Ty1, _Ty2> : _Decayed_cond_oper<_Ty1, _Ty2> {};

template <class _Ty1, class _Ty2>
struct common_type<_Ty1, _Ty2> : _Common_type2<_Ty1, _Ty2> {};

template <class _Void, class _Ty1, class _Ty2, class... _Rest>
struct _Common_type3 {};

template <class _Ty1, class _Ty2, class... _Rest>
struct _Common_type3<void_t<common_type_t<_Ty1, _Ty2>>, _Ty1, _Ty2, _Rest...>
    : common_type<common_type_t<_Ty1, _Ty2>, _Rest...> {};

template <class _Ty1, class _Ty2, class... _Rest>
struct common_type<_Ty1, _Ty2, _Rest...> : _Common_type3<void, _Ty1, _Ty2, _Rest...> {};

// STRUCT TEMPLATE _Identity
template <class _Ty>
struct _Identity {
    using type = _Ty;
};
template <class _Ty>
using _Identity_t = typename _Identity<_Ty>::type;

#if _HAS_CXX20
// STRUCT TEMPLATE type_identity
template <class _Ty>
struct type_identity {
    using type = _Ty;
};
template <class _Ty>
using type_identity_t = typename type_identity<_Ty>::type;
#endif // _HAS_CXX20

// STRUCT TEMPLATE _Is_specialization
template <class _Type, template <class...> class _Template>
_INLINE_VAR constexpr bool _Is_specialization_v = false; // true if and only if _Type is a specialization of _Template
template <template <class...> class _Template, class... _Types>
_INLINE_VAR constexpr bool _Is_specialization_v<_Template<_Types...>, _Template> = true;

template <class _Type, template <class...> class _Template>
struct _Is_specialization : bool_constant<_Is_specialization_v<_Type, _Template>> {};

// FUNCTION TEMPLATE forward
template <class _Ty>
_NODISCARD constexpr _Ty&& forward(
    remove_reference_t<_Ty>& _Arg) noexcept { // forward an lvalue as either an lvalue or an rvalue
    return static_cast<_Ty&&>(_Arg);
}

template <class _Ty>
_NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept { // forward an rvalue as an rvalue
    static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
    return static_cast<_Ty&&>(_Arg);
}

// FUNCTION TEMPLATE move
template <class _Ty>
_NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) noexcept { // forward _Arg as movable
    return static_cast<remove_reference_t<_Ty>&&>(_Arg);
}

// FUNCTION TEMPLATE move_if_noexcept
template <class _Ty>
_NODISCARD constexpr conditional_t<!is_nothrow_move_constructible_v<_Ty> && is_copy_constructible_v<_Ty>, const _Ty&,
    _Ty&&>
    move_if_noexcept(_Ty& _Arg) noexcept { // forward _Arg as movable, sometimes
    return _STD move(_Arg);
}

template <class _Ty>
class reference_wrapper;

#define _CONCATX(x, y) x##y
#define _CONCAT(x, y) _CONCATX(x, y)

#define _IMPLEMENT_INVOKE(NAME_PREFIX, CONSTEXPR)                                                                      \
    /* FUNCTION TEMPLATE invoke */                                                                                     \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmf_object) { /* INVOKE a pointer to member function on an object */          \
        template <class _Decayed, class _Ty1, class... _Types2>                                                        \
        static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2)                                  \
            _NOEXCEPT_COND(noexcept((_STD forward<_Ty1>(_Arg1).*_Pmf)(_STD forward<_Types2>(_Args2)...)))              \
                -> decltype((_STD forward<_Ty1>(_Arg1).*_Pmf)(                                                         \
                    _STD forward<_Types2>(_Args2)...)) { /* INVOKE a pointer to member function on an object */        \
            return (_STD forward<_Ty1>(_Arg1).*_Pmf)(_STD forward<_Types2>(_Args2)...);                                \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(                                                                                                    \
        NAME_PREFIX, _Invoker_pmf_refwrap) { /* INVOKE a pointer to member function on a reference_wrapper */          \
        template <class _Decayed, class _Ty1, class... _Types2>                                                        \
        static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2)                                  \
            _NOEXCEPT_COND(noexcept((_STD forward<_Ty1>(_Arg1).get().*_Pmf)(_STD forward<_Types2>(_Args2)...)))        \
                -> decltype((_STD forward<_Ty1>(_Arg1).get().*_Pmf)(_STD forward<_Types2>(                             \
                    _Args2)...)) { /* INVOKE a pointer to member function on a reference_wrapper */                    \
            return (_STD forward<_Ty1>(_Arg1).get().*_Pmf)(_STD forward<_Types2>(_Args2)...);                          \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmf_pointer) { /* INVOKE a pointer to member function on a [smart] pointer */ \
        template <class _Decayed, class _Ty1, class... _Types2>                                                        \
        static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2)                                  \
            _NOEXCEPT_COND(noexcept(((*_STD forward<_Ty1>(_Arg1)).*_Pmf)(_STD forward<_Types2>(_Args2)...)))           \
                -> decltype(((*_STD forward<_Ty1>(_Arg1)).*_Pmf)(_STD forward<_Types2>(                                \
                    _Args2)...)) { /* INVOKE a pointer to member function on a [smart] pointer */                      \
            return ((*_STD forward<_Ty1>(_Arg1)).*_Pmf)(_STD forward<_Types2>(_Args2)...);                             \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmd_object) { /* INVOKE a pointer to member data on an object */              \
        template <class _Decayed, class _Ty1>                                                                          \
        static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1)                                                       \
            _NOEXCEPT_COND(noexcept(_STD forward<_Ty1>(_Arg1).*_Pmd))                                                  \
                -> decltype(_STD forward<_Ty1>(_Arg1).*_Pmd) { /* INVOKE a pointer to member data on an object */      \
            return _STD forward<_Ty1>(_Arg1).*_Pmd;                                                                    \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmd_refwrap) { /* INVOKE a pointer to member data on a reference_wrapper */   \
        template <class _Decayed, class _Ty1>                                                                          \
        static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1)                                                       \
            _NOEXCEPT_COND(noexcept(_STD forward<_Ty1>(_Arg1).get().*_Pmd)) -> decltype(                               \
                _STD forward<_Ty1>(_Arg1).get().*_Pmd) { /* INVOKE a pointer to member data on a reference_wrapper */  \
            return _STD forward<_Ty1>(_Arg1).get().*_Pmd;                                                              \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmd_pointer) { /* INVOKE a pointer to member data on a [smart] pointer */     \
        template <class _Decayed, class _Ty1>                                                                          \
        static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1)                                                       \
            _NOEXCEPT_COND(noexcept((*_STD forward<_Ty1>(_Arg1)).*_Pmd)) -> decltype(                                  \
                (*_STD forward<_Ty1>(_Arg1)).*_Pmd) { /* INVOKE a pointer to member data on a [smart] pointer */       \
            return (*_STD forward<_Ty1>(_Arg1)).*_Pmd;                                                                 \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_functor) { /* INVOKE a function object */                                     \
        template <class _Callable, class... _Types>                                                                    \
        static CONSTEXPR auto _Call(_Callable&& _Obj, _Types&&... _Args)                                               \
            _NOEXCEPT_COND(noexcept(_STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...))) -> decltype(       \
                _STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...)) { /* INVOKE a function object */        \
            return _STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...);                                      \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    template <class _Callable, class _Ty1, class _Removed_cvref = _Remove_cvref_t<_Callable>,                          \
        bool _Is_pmf = is_member_function_pointer_v<_Removed_cvref>,                                                   \
        bool _Is_pmd = is_member_object_pointer_v<_Removed_cvref>>                                                     \
    struct _CONCAT(NAME_PREFIX, _Invoker1);                                                                            \
                                                                                                                       \
    template <class _Callable, class _Ty1, class _Removed_cvref>                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, true, false>                               \
        : conditional_t<is_base_of_v<typename _Is_memfunptr<_Removed_cvref>::_Class_type, remove_reference_t<_Ty1>>,   \
              _CONCAT(NAME_PREFIX, _Invoker_pmf_object),                                                               \
              conditional_t<_Is_specialization_v<_Remove_cvref_t<_Ty1>, reference_wrapper>,                            \
                  _CONCAT(NAME_PREFIX, _Invoker_pmf_refwrap),                                                          \
                  _CONCAT(NAME_PREFIX, _Invoker_pmf_pointer)>> { /* pointer to member function */                      \
    };                                                                                                                 \
                                                                                                                       \
    template <class _Callable, class _Ty1, class _Removed_cvref>                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, false, true>                               \
        : conditional_t<                                                                                               \
              is_base_of_v<typename _Is_member_object_pointer<_Removed_cvref>::_Class_type, remove_reference_t<_Ty1>>, \
              _CONCAT(NAME_PREFIX, _Invoker_pmd_object),                                                               \
              conditional_t<_Is_specialization_v<_Remove_cvref_t<_Ty1>, reference_wrapper>,                            \
                  _CONCAT(NAME_PREFIX, _Invoker_pmd_refwrap),                                                          \
                  _CONCAT(NAME_PREFIX, _Invoker_pmd_pointer)>> { /* pointer to member data */                          \
    };                                                                                                                 \
                                                                                                                       \
    template <class _Callable, class _Ty1, class _Removed_cvref>                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, false, false>                              \
        : _CONCAT(NAME_PREFIX, _Invoker_functor) { /* function object */                                               \
    };                                                                                                                 \
                                                                                                                       \
    template <class _Callable, class... _Types>                                                                        \
    struct _CONCAT(NAME_PREFIX, _Invoker);                                                                             \
                                                                                                                       \
    template <class _Callable>                                                                                         \
    struct _CONCAT(NAME_PREFIX, _Invoker)<_Callable> : _CONCAT(NAME_PREFIX, _Invoker_functor) { /* zero arguments */   \
    };                                                                                                                 \
                                                                                                                       \
    template <class _Callable, class _Ty1, class... _Types2>                                                           \
    struct _CONCAT(NAME_PREFIX, _Invoker)<_Callable, _Ty1, _Types2...>                                                 \
        : _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1> { /* one or more arguments */                               \
    };                                                                                                                 \
                                                                                                                       \
    template <class _Callable, class... _Types>                                                                        \
    CONSTEXPR auto _CONCAT(NAME_PREFIX, invoke)(_Callable && _Obj, _Types && ... _Args)                                \
        _NOEXCEPT_COND(noexcept(_CONCAT(NAME_PREFIX, _Invoker) < _Callable,                                            \
                           _Types... > ::_Call(_STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...)))        \
            ->decltype(_CONCAT(NAME_PREFIX, _Invoker) < _Callable,                                                     \
                _Types... > ::_Call(_STD forward<_Callable>(_Obj),                                                     \
                                _STD forward<_Types>(_Args)...)) { /* INVOKE a callable object */                      \
        return _CONCAT(NAME_PREFIX, _Invoker)<_Callable, _Types...>::_Call(                                            \
            _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...);                                            \
    }

_IMPLEMENT_INVOKE(_EMPTY_ARGUMENT, inline)

#if _HAS_CXX17
// constexpr IMPLEMENTATION OF invoke
_IMPLEMENT_INVOKE(_C_, constexpr)
#endif // _HAS_CXX17

#undef _IMPLEMENT_INVOKE

template <class _Rx, bool = is_void_v<_Rx>>
struct _Invoker_ret {}; // helper to give INVOKE an explicit return type; avoids undesirable Expression SFINAE

struct _Unforced {}; // tag to distinguish bind() from bind<R>()

template <class _Cv_void>
struct _Invoker_ret<_Cv_void, true> { // selected for _Rx being cv void
    template <class... _Valtys>
    static void _Call(_Valtys&&... _Vals) { // INVOKE, "implicitly" converted to void
        _STD invoke(_STD forward<_Valtys>(_Vals)...);
    }
};

template <class _Rx>
struct _Invoker_ret<_Rx, false> { // selected for all _Rx other than cv void and _Unforced
    template <class... _Valtys>
    static _Rx _Call(_Valtys&&... _Vals) { // INVOKE, implicitly converted to _Rx
        return _STD invoke(_STD forward<_Valtys>(_Vals)...);
    }
};

template <>
struct _Invoker_ret<_Unforced, false> { // selected for _Rx being _Unforced
    template <class... _Valtys>
    static auto _Call(_Valtys&&... _Vals)
        -> decltype(_STD invoke(_STD forward<_Valtys>(_Vals)...)) { // INVOKE, unchanged
        return _STD invoke(_STD forward<_Valtys>(_Vals)...);
    }
};

// TYPE TRAITS FOR invoke()
template <class _To>
void _Implicitly_convert_to(_To) noexcept;

template <class _From, class _To, bool = is_convertible_v<_From, _To>>
struct _Is_nothrow_convertible : bool_constant<_NOEXCEPT_OPER(_Implicitly_convert_to<_To>(_STD declval<_From>()))> {
    // determine whether _From is nothrow-convertible to _To
};

template <class _From, class _To>
struct _Is_nothrow_convertible<_From, _To, false> : false_type {
    // determine whether _From is nothrow-convertible to _To
};

template <class _Void, class... _Types>
struct _Invoke_traits { // selected when _Callable isn't callable with _Args
    using _Is_invocable         = false_type;
    using _Is_nothrow_invocable = false_type;
    template <class _Rx>
    using _Is_invocable_r = false_type;
    template <class _Rx>
    using _Is_nothrow_invocable_r = false_type;
};

template <class... _Types>
struct _Invoke_traits<void_t<decltype(_STD invoke(_STD declval<_Types>()...))>,
    _Types...> { // selected when _Callable is callable with _Args
    using type                  = decltype(_STD invoke(_STD declval<_Types>()...));
    using _Is_invocable         = true_type;
    using _Is_nothrow_invocable = bool_constant<_NOEXCEPT_OPER(_STD invoke(_STD declval<_Types>()...))>;
    template <class _Rx>
    using _Is_invocable_r = bool_constant<disjunction_v<is_void<_Rx>, is_convertible<type, _Rx>>>;
    template <class _Rx>
    using _Is_nothrow_invocable_r = bool_constant<
        conjunction_v<_Is_nothrow_invocable, disjunction<is_void<_Rx>, _Is_nothrow_convertible<type, _Rx>>>>;
};

// STRUCT TEMPLATE result_of
template <class _Fty>
struct _CXX17_DEPRECATE_RESULT_OF result_of { // explain usage
    static_assert(_Always_false<_Fty>, "result_of<CallableType> is invalid; use "
                                       "result_of<CallableType(zero or more argument types)> instead.");
};

#define _RESULT_OF(CALL_OPT, X1, X2, X3)                                                                   \
    template <class _Callable, class... _Args>                                                             \
    struct _CXX17_DEPRECATE_RESULT_OF result_of<_Callable CALL_OPT(_Args...)>                              \
        : _Invoke_traits<void, _Callable, _Args...> { /* template to determine result of call operation */ \
    };

_NON_MEMBER_CALL(_RESULT_OF, X1, X2, X3)
#undef _RESULT_OF

#pragma warning(push)
#pragma warning(disable : 4996) // was declared deprecated
template <class _Ty>
using result_of_t _CXX17_DEPRECATE_RESULT_OF = typename result_of<_Ty>::type;
#pragma warning(pop)

template <class _Callable, class... _Args>
using _Invoke_result_t = typename _Invoke_traits<void, _Callable, _Args...>::type;

template <class _Rx, class _Callable, class... _Args>
using _Is_invocable_r_ = typename _Invoke_traits<void, _Callable, _Args...>::template _Is_invocable_r<_Rx>;

template <class _Rx, class _Callable, class... _Args>
struct _Is_invocable_r : _Is_invocable_r_<_Rx, _Callable, _Args...> {
    // determines whether _Callable is callable with _Args and return type _Rx
};

#if _HAS_CXX17
// STRUCT TEMPLATE invoke_result
template <class _Callable, class... _Args>
struct invoke_result : _Invoke_traits<void, _Callable, _Args...> {
    // determine the result type of invoking _Callable with _Args
};

template <class _Callable, class... _Args>
using invoke_result_t = typename _Invoke_traits<void, _Callable, _Args...>::type;

// STRUCT TEMPLATE is_invocable
template <class _Callable, class... _Args>
struct is_invocable : _Invoke_traits<void, _Callable, _Args...>::_Is_invocable {
    // determines whether _Callable is callable with _Args
};

template <class _Callable, class... _Args>
inline constexpr bool is_invocable_v = _Invoke_traits<void, _Callable, _Args...>::_Is_invocable::value;

// STRUCT TEMPLATE is_nothrow_invocable
template <class _Callable, class... _Args>
struct is_nothrow_invocable : _Invoke_traits<void, _Callable, _Args...>::_Is_nothrow_invocable {
    // determines whether _Callable is nothrow-callable with _Args
};

template <class _Callable, class... _Args>
inline constexpr bool is_nothrow_invocable_v = _Invoke_traits<void, _Callable, _Args...>::_Is_nothrow_invocable::value;

// STRUCT TEMPLATE is_invocable_r
template <class _Rx, class _Callable, class... _Args>
struct is_invocable_r : _Is_invocable_r_<_Rx, _Callable, _Args...> {
    // determines whether _Callable is callable with _Args and return type _Rx
};

template <class _Rx, class _Callable, class... _Args>
inline constexpr bool is_invocable_r_v = _Is_invocable_r_<_Rx, _Callable, _Args...>::value;

// STRUCT TEMPLATE is_nothrow_invocable_r
template <class _Rx, class _Callable, class... _Args>
struct is_nothrow_invocable_r : _Invoke_traits<void, _Callable, _Args...>::template _Is_nothrow_invocable_r<_Rx> {
    // determines whether _Callable is nothrow-callable with _Args and return type _Rx
};

template <class _Rx, class _Callable, class... _Args>
inline constexpr bool is_nothrow_invocable_r_v =
    _Invoke_traits<void, _Callable, _Args...>::template _Is_nothrow_invocable_r<_Rx>::value;
#endif // _HAS_CXX17


// STRUCT TEMPLATE _Weak_types
template <class _Ty, class = void>
struct _Weak_result_type {}; // default definition

#pragma warning(push)
#pragma warning(disable : 4996) // was declared deprecated
template <class _Ty>
struct _Weak_result_type<_Ty, void_t<typename _Ty::result_type>> { // defined if _Ty::result_type exists
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef typename _Ty::result_type result_type;
};
#pragma warning(pop)

template <class _Ty, class = void>
struct _Weak_argument_type : _Weak_result_type<_Ty> {}; // default definition

#pragma warning(push)
#pragma warning(disable : 4996) // was declared deprecated
template <class _Ty>
struct _Weak_argument_type<_Ty, void_t<typename _Ty::argument_type>>
    : _Weak_result_type<_Ty> { // defined if _Ty::argument_type exists
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef typename _Ty::argument_type argument_type;
};
#pragma warning(pop)

template <class _Ty, class = void>
struct _Weak_binary_args : _Weak_argument_type<_Ty> {}; // default definition

#pragma warning(push)
#pragma warning(disable : 4996) // was declared deprecated
template <class _Ty>
struct _Weak_binary_args<_Ty, void_t<typename _Ty::first_argument_type,
                                  typename _Ty::second_argument_type>>
    : _Weak_argument_type<_Ty> { // defined if both types exist
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef typename _Ty::first_argument_type first_argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef typename _Ty::second_argument_type second_argument_type;
};
#pragma warning(pop)

template <class _Ty>
struct _Weak_types { // provide nested types (sometimes)
    using _Is_f_or_pf = _Is_function<remove_pointer_t<_Ty>>;
    using _Is_pmf     = _Is_memfunptr<remove_cv_t<_Ty>>;
    using type        = conditional_t<_Is_f_or_pf::_Bool_type::value, _Is_f_or_pf,
        conditional_t<_Is_pmf::_Bool_type::value, _Is_pmf, _Weak_binary_args<_Ty>>>;
};

// CLASS TEMPLATE reference_wrapper
template <class _Ty>
void _Refwrap_ctor_fun(_Identity_t<_Ty&>) noexcept;
template <class _Ty>
void _Refwrap_ctor_fun(_Identity_t<_Ty&&>) = delete;

template <class _Ty, class _Uty, class = void>
struct _Refwrap_has_ctor_from : false_type {};

template <class _Ty, class _Uty>
struct _Refwrap_has_ctor_from<_Ty, _Uty, void_t<decltype(_Refwrap_ctor_fun<_Ty>(_STD declval<_Uty>()))>> : true_type {};

template <class _Ty>
class reference_wrapper : public _Weak_types<_Ty>::type { // stand-in for an assignable reference
public:
    static_assert(is_object_v<_Ty> || is_function_v<_Ty>,
        "reference_wrapper<T> requires T to be an object type or a function type.");

    using type = _Ty;

    template <class _Uty, enable_if_t<conjunction_v<negation<is_same<_Remove_cvref_t<_Uty>, reference_wrapper>>,
                                          _Refwrap_has_ctor_from<_Ty, _Uty>>,
                              int> = 0>
    reference_wrapper(_Uty&& _Val) _NOEXCEPT_COND(noexcept(_Refwrap_ctor_fun<_Ty>(_STD declval<_Uty>()))) {
        _Ty& _Ref = _STD forward<_Uty>(_Val);
        _Ptr      = _STD addressof(_Ref);
    }

    operator _Ty&() const noexcept {
        return *_Ptr;
    }

    _NODISCARD _Ty& get() const noexcept {
        return *_Ptr;
    }

    template <class... _Types>
    auto operator()(_Types&&... _Args) const -> decltype(_STD invoke(get(), _STD forward<_Types>(_Args)...)) {
        return _STD invoke(get(), _STD forward<_Types>(_Args)...);
    }

private:
    _Ty* _Ptr;
};

#if _HAS_CXX17
template <class _Ty>
reference_wrapper(_Ty&)->reference_wrapper<_Ty>;
#endif // _HAS_CXX17

// FUNCTION TEMPLATES ref AND cref
template <class _Ty>
_NODISCARD inline reference_wrapper<_Ty> ref(_Ty& _Val) noexcept {
    return reference_wrapper<_Ty>(_Val);
}

template <class _Ty>
void ref(const _Ty&&) = delete;

template <class _Ty>
_NODISCARD inline reference_wrapper<_Ty> ref(reference_wrapper<_Ty> _Val) noexcept {
    return _STD ref(_Val.get());
}

template <class _Ty>
_NODISCARD inline reference_wrapper<const _Ty> cref(const _Ty& _Val) noexcept {
    return reference_wrapper<const _Ty>(_Val);
}

template <class _Ty>
void cref(const _Ty&&) = delete;

template <class _Ty>
_NODISCARD inline reference_wrapper<const _Ty> cref(reference_wrapper<_Ty> _Val) noexcept {
    return _STD cref(_Val.get());
}

#if _HAS_CXX20
// STRUCT TEMPLATE unwrap_reference
template <class _Ty>
struct unwrap_reference {
    using type = _Ty;
};
template <class _Ty>
struct unwrap_reference<reference_wrapper<_Ty>> {
    using type = _Ty&;
};
template <class _Ty>
using unwrap_reference_t = typename unwrap_reference<_Ty>::type;

// STRUCT TEMPLATE unwrap_ref_decay
template <class _Ty>
using unwrap_ref_decay_t = unwrap_reference_t<decay_t<_Ty>>;
template <class _Ty>
struct unwrap_ref_decay {
    using type = unwrap_ref_decay_t<_Ty>;
};
#endif // _HAS_CXX20

// STRUCT TEMPLATE _Is_swappable
template <class _Ty>
struct _Is_swappable;

// STRUCT TEMPLATE _Is_nothrow_swappable
template <class _Ty>
struct _Is_nothrow_swappable;

// FUNCTION TEMPLATE swap
#if _HAS_CXX17
template <class _Ty, class = enable_if_t<is_move_constructible_v<_Ty> && is_move_assignable_v<_Ty>>>
inline
#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv
template <class _Ty, class = void>
inline
#endif // _HAS_CXX17
    void
    swap(_Ty&, _Ty&) _NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>);

template <class _Ty, size_t _Size, class = enable_if_t<_Is_swappable<_Ty>::value>>
inline void swap(_Ty (&)[_Size], _Ty (&)[_Size]) _NOEXCEPT_COND(_Is_nothrow_swappable<_Ty>::value);

// STRUCT TEMPLATE _Swappable_with_helper
template <class _Ty1, class _Ty2, class = void>
struct _Swappable_with_helper : false_type {}; // swap(declval<_Ty1>(), declval<_Ty2>()) is not valid

template <class _Ty1, class _Ty2>
struct _Swappable_with_helper<_Ty1, _Ty2, void_t<decltype(swap(_STD declval<_Ty1>(), _STD declval<_Ty2>()))>>
    : true_type {}; // swap(declval<_Ty1>(), declval<_Ty2>()) is valid

// STRUCT TEMPLATE _Is_swappable_with
template <class _Ty1, class _Ty2>
struct _Is_swappable_with
    : bool_constant<conjunction_v<_Swappable_with_helper<_Ty1, _Ty2>, _Swappable_with_helper<_Ty2, _Ty1>>> {
    // Determine if expressions with type and value category _Ty1 and _Ty2 can be swapped (and vice versa)
};

// STRUCT TEMPLATE _Is_swappable
template <class _Ty>
struct _Is_swappable : _Is_swappable_with<add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<_Ty>>::type {
    // Determine if _Ty lvalues satisfy is_swappable_with
};

// STRUCT TEMPLATE _Swap_cannot_throw
template <class _Ty1, class _Ty2>
struct _Swap_cannot_throw : bool_constant<_NOEXCEPT_OPER(swap(_STD declval<_Ty1>(), _STD declval<_Ty2>()))
                                          && _NOEXCEPT_OPER(swap(_STD declval<_Ty2>(), _STD declval<_Ty1>()))> {
    // Determine if expressions with type and value category _Ty1 and _Ty2
    // (presumed to satisfy is_swappable_with) can be swapped without emitting exceptions
};

// STRUCT TEMPLATE _Is_nothrow_swappable_with
template <class _Ty1, class _Ty2>
struct _Is_nothrow_swappable_with
    : bool_constant<conjunction_v<_Is_swappable_with<_Ty1, _Ty2>, _Swap_cannot_throw<_Ty1, _Ty2>>> {
    // Determine if expressions with type and value category _Ty1 and _Ty2
    // satisfy is_swappable_with, and can be swapped without emitting exceptions
};

// STRUCT TEMPLATE _Is_nothrow_swappable
template <class _Ty>
struct _Is_nothrow_swappable
    : _Is_nothrow_swappable_with<add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<_Ty>>::type {
    // Determine if _Ty lvalues satisfy is_nothrow_swappable_with
};

#if _HAS_CXX17
// STRUCT TEMPLATE is_swappable_with
template <class _Ty1, class _Ty2>
struct is_swappable_with : _Is_swappable_with<_Ty1, _Ty2>::type {
    // Determine if expressions with type and value category _Ty1 and _Ty2
    // can be swapped (and vice versa)
};

template <class _Ty1, class _Ty2>
inline constexpr bool is_swappable_with_v =
    conjunction_v<_Swappable_with_helper<_Ty1, _Ty2>, _Swappable_with_helper<_Ty2, _Ty1>>;

// STRUCT TEMPLATE is_swappable
template <class _Ty>
struct is_swappable : _Is_swappable<_Ty>::type {}; // Determine if _Ty lvalues satisfy is_swappable_with

template <class _Ty>
inline constexpr bool is_swappable_v = _Is_swappable<_Ty>::value;

// STRUCT TEMPLATE is_nothrow_swappable_with
template <class _Ty1, class _Ty2>
struct is_nothrow_swappable_with : _Is_nothrow_swappable_with<_Ty1, _Ty2>::type {
    // Determine if expressions with type and value category _Ty1 and _Ty2
    // satisfy is_swappable_with, and can be swapped without emitting exceptions
};

template <class _Ty1, class _Ty2>
inline constexpr bool is_nothrow_swappable_with_v = _Is_nothrow_swappable_with<_Ty1, _Ty2>::value;

// STRUCT TEMPLATE is_nothrow_swappable
template <class _Ty>
struct is_nothrow_swappable : _Is_nothrow_swappable<_Ty>::type {
    // Determine if _Ty lvalues satisfy is_nothrow_swappable_with
};

template <class _Ty>
inline constexpr bool is_nothrow_swappable_v = _Is_nothrow_swappable<_Ty>::value;
#endif // _HAS_CXX17

// TYPE TRAIT _Is_trivially_swappable
namespace _Has_ADL_swap_detail {
    void swap(); // undefined (deliberate shadowing)

    template <class, class = void>
    struct _Has_ADL_swap : false_type {};
    template <class _Ty>
    struct _Has_ADL_swap<_Ty, void_t<decltype(swap(_STD declval<_Ty&>(), _STD declval<_Ty&>()))>> : true_type {};
} // namespace _Has_ADL_swap_detail
using _Has_ADL_swap_detail::_Has_ADL_swap;

template <class _Ty>
_INLINE_VAR constexpr bool _Is_trivially_swappable_v = conjunction_v<is_trivially_destructible<_Ty>,
    is_trivially_move_constructible<_Ty>, is_trivially_move_assignable<_Ty>, negation<_Has_ADL_swap<_Ty>>>;

template <class _Ty>
struct _Is_trivially_swappable : bool_constant<_Is_trivially_swappable_v<_Ty>> {
    // true_type if and only if it is valid to swap two _Ty lvalues by exchanging object representations.
};

// BITMASK OPERATIONS
#define _BITMASK_OPS(_BITMASK)                                                                                      \
    _NODISCARD constexpr _BITMASK operator&(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left & _Right */ \
        using _IntTy = _STD underlying_type_t<_BITMASK>;                                                            \
        return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) & static_cast<_IntTy>(_Right));                     \
    }                                                                                                               \
                                                                                                                    \
    _NODISCARD constexpr _BITMASK operator|(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left | _Right */ \
        using _IntTy = _STD underlying_type_t<_BITMASK>;                                                            \
        return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) | static_cast<_IntTy>(_Right));                     \
    }                                                                                                               \
                                                                                                                    \
    _NODISCARD constexpr _BITMASK operator^(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left ^ _Right */ \
        using _IntTy = _STD underlying_type_t<_BITMASK>;                                                            \
        return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) ^ static_cast<_IntTy>(_Right));                     \
    }                                                                                                               \
                                                                                                                    \
    constexpr _BITMASK& operator&=(_BITMASK& _Left, _BITMASK _Right) noexcept { /* return _Left &= _Right */        \
        return _Left = _Left & _Right;                                                                              \
    }                                                                                                               \
                                                                                                                    \
    constexpr _BITMASK& operator|=(_BITMASK& _Left, _BITMASK _Right) noexcept { /* return _Left |= _Right */        \
        return _Left = _Left | _Right;                                                                              \
    }                                                                                                               \
                                                                                                                    \
    constexpr _BITMASK& operator^=(_BITMASK& _Left, _BITMASK _Right) noexcept { /* return _Left ^= _Right */        \
        return _Left = _Left ^ _Right;                                                                              \
    }                                                                                                               \
                                                                                                                    \
    _NODISCARD constexpr _BITMASK operator~(_BITMASK _Left) noexcept { /* return ~_Left */                          \
        using _IntTy = _STD underlying_type_t<_BITMASK>;                                                            \
        return static_cast<_BITMASK>(~static_cast<_IntTy>(_Left));                                                  \
    }                                                                                                               \
                                                                                                                    \
    _NODISCARD constexpr bool _Bitmask_includes(                                                                    \
        _BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) != _BITMASK{} */               \
        return (_Left & _Elements) != _BITMASK{};                                                                   \
    }                                                                                                               \
                                                                                                                    \
    _NODISCARD constexpr bool _Bitmask_includes_all(                                                                \
        _BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) == _Elements */                \
        return (_Left & _Elements) == _Elements;                                                                    \
    }

// FNV-1a UTILITIES
// These functions are extremely performance sensitive, check examples like
// that in VSO#653642 before making changes.
#if defined(_WIN64)
_INLINE_VAR constexpr size_t _FNV_offset_basis = 14695981039346656037ULL;
_INLINE_VAR constexpr size_t _FNV_prime        = 1099511628211ULL;
#else // defined(_WIN64)
_INLINE_VAR constexpr size_t _FNV_offset_basis = 2166136261U;
_INLINE_VAR constexpr size_t _FNV_prime        = 16777619U;
#endif // defined(_WIN64)

_NODISCARD inline size_t _Fnv1a_append_bytes(size_t _Val, const unsigned char* const _First,
    const size_t _Count) noexcept { // accumulate range [_First, _First + _Count) into partial FNV-1a hash _Val
    for (size_t _Idx = 0; _Idx < _Count; ++_Idx) {
        _Val ^= static_cast<size_t>(_First[_Idx]);
        _Val *= _FNV_prime;
    }

    return _Val;
}

template <class _Ty>
_NODISCARD inline size_t _Fnv1a_append_range(const size_t _Val, const _Ty* const _First,
    const _Ty* const _Last) noexcept { // accumulate range [_First, _Last) into partial FNV-1a hash _Val
    static_assert(is_trivial_v<_Ty>, "Only trivial types can be directly hashed.");
    const auto _Firstb = reinterpret_cast<const unsigned char*>(_First);
    const auto _Lastb  = reinterpret_cast<const unsigned char*>(_Last);
    return _Fnv1a_append_bytes(_Val, _Firstb, static_cast<size_t>(_Lastb - _Firstb));
}

template <class _Kty>
_NODISCARD inline size_t _Fnv1a_append_value(
    const size_t _Val, const _Kty& _Keyval) noexcept { // accumulate _Keyval into partial FNV-1a hash _Val
    static_assert(is_trivial_v<_Kty>, "Only trivial types can be directly hashed.");
    return _Fnv1a_append_bytes(_Val, &reinterpret_cast<const unsigned char&>(_Keyval), sizeof(_Kty));
}

// FUNCTION TEMPLATE _Hash_representation
template <class _Kty>
_NODISCARD inline size_t _Hash_representation(
    const _Kty& _Keyval) noexcept { // bitwise hashes the representation of a key
    return _Fnv1a_append_value(_FNV_offset_basis, _Keyval);
}

// FUNCTION TEMPLATE _Hash_array_representation
template <class _Kty>
_NODISCARD inline size_t _Hash_array_representation(
    const _Kty* const _First, const size_t _Count) noexcept { // bitwise hashes the representation of an array
    static_assert(is_trivial_v<_Kty>, "Only trivial types can be directly hashed.");
    return _Fnv1a_append_bytes(
        _FNV_offset_basis, reinterpret_cast<const unsigned char*>(_First), _Count * sizeof(_Kty));
}

// STRUCT TEMPLATE _Conditionally_enabled_hash
template <class _Kty>
struct hash;

template <class _Kty, bool _Enabled>
struct _Conditionally_enabled_hash { // conditionally enabled hash base
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Kty argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef size_t result_type;

    _NODISCARD size_t operator()(const _Kty& _Keyval) const _NOEXCEPT_COND(
        noexcept(hash<_Kty>::_Do_hash(_Keyval))) { // hash _Keyval to size_t value by pseudorandomizing transform
        return hash<_Kty>::_Do_hash(_Keyval);
    }
};

template <class _Kty>
struct _Conditionally_enabled_hash<_Kty, false> { // conditionally disabled hash base
    _Conditionally_enabled_hash()                                   = delete;
    _Conditionally_enabled_hash(const _Conditionally_enabled_hash&) = delete;
    _Conditionally_enabled_hash(_Conditionally_enabled_hash&&)      = delete;
    _Conditionally_enabled_hash& operator=(const _Conditionally_enabled_hash&) = delete;
    _Conditionally_enabled_hash& operator=(_Conditionally_enabled_hash&&) = delete;
};

// STRUCT TEMPLATE hash
template <class _Kty>
struct hash
    : _Conditionally_enabled_hash<_Kty,
          !is_const_v<_Kty> && !is_volatile_v<_Kty> && (is_enum_v<_Kty> || is_integral_v<_Kty> || is_pointer_v<_Kty>)> {
    // hash functor primary template (handles enums, integrals, and pointers)
    static size_t _Do_hash(
        const _Kty& _Keyval) noexcept { // hash _Keyval to size_t value by pseudorandomizing transform
        return _Hash_representation(_Keyval);
    }
};

template <>
struct hash<float> {
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef float argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef size_t result_type;
    _NODISCARD size_t operator()(const float _Keyval) const
        noexcept { // hash _Keyval to size_t value by pseudorandomizing transform
        return _Hash_representation(_Keyval == 0.0F ? 0.0F : _Keyval); // map -0 to 0
    }
};

template <>
struct hash<double> {
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef double argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef size_t result_type;
    _NODISCARD size_t operator()(const double _Keyval) const
        noexcept { // hash _Keyval to size_t value by pseudorandomizing transform
        return _Hash_representation(_Keyval == 0.0 ? 0.0 : _Keyval); // map -0 to 0
    }
};

template <>
struct hash<long double> {
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef long double argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef size_t result_type;
    _NODISCARD size_t operator()(const long double _Keyval) const
        noexcept { // hash _Keyval to size_t value by pseudorandomizing transform
        return _Hash_representation(_Keyval == 0.0L ? 0.0L : _Keyval); // map -0 to 0
    }
};

template <>
struct hash<nullptr_t> {
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef nullptr_t argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef size_t result_type;
    _NODISCARD size_t operator()(nullptr_t) const
        noexcept { // hash nullptr_t to size_t value by pseudorandomizing transform
        void* _Null{};
        return _Hash_representation(_Null);
    }
};

// STRUCT TEMPLATE _Is_nothrow_hashable
template <class _Kty, class = void>
struct _Is_nothrow_hashable : false_type {}; // tests if std::hash can hash _Kty with noexcept

template <class _Kty>
struct _Is_nothrow_hashable<_Kty, void_t<decltype(hash<_Kty>{}(_STD declval<const _Kty&>()))>>
    : bool_constant<_NOEXCEPT_OPER(hash<_Kty>{}(_STD declval<const _Kty&>()))> {};

#if _HAS_TR1_NAMESPACE
#pragma warning(push)
#pragma warning(disable : 4996) // was declared deprecated
namespace _DEPRECATE_TR1_NAMESPACE tr1 {
    using _STD add_const;
    using _STD add_cv;
    using _STD add_pointer;
    using _STD add_volatile;
    using _STD aligned_storage;
    using _STD alignment_of;
    using _STD conditional;
    using _STD decay;
    using _STD enable_if;
    using _STD extent;
    using _STD false_type;
    using _STD has_virtual_destructor;
    using _STD integral_constant;
    using _STD is_abstract;
    using _STD is_arithmetic;
    using _STD is_array;
    using _STD is_base_of;
    using _STD is_class;
    using _STD is_compound;
    using _STD is_const;
    using _STD is_convertible;
    using _STD is_empty;
    using _STD is_enum;
    using _STD is_floating_point;
    using _STD is_function;
    using _STD is_fundamental;
    using _STD is_integral;
    using _STD is_member_function_pointer;
    using _STD is_member_object_pointer;
    using _STD is_member_pointer;
    using _STD is_object;
    using _STD is_pod;
    using _STD is_pointer;
    using _STD is_polymorphic;
    using _STD is_reference;
    using _STD is_same;
    using _STD is_scalar;
    using _STD is_signed;
    using _STD is_union;
    using _STD is_unsigned;
    using _STD is_void;
    using _STD is_volatile;
    using _STD make_signed;
    using _STD make_unsigned;
    using _STD rank;
    using _STD remove_all_extents;
    using _STD remove_const;
    using _STD remove_cv;
    using _STD remove_extent;
    using _STD remove_pointer;
    using _STD remove_reference;
    using _STD remove_volatile;
    using _STD true_type;
    using _STD cref;
    using _STD ref;
    using _STD reference_wrapper;
    using _STD result_of;
    using _STD hash;
} // namespace tr1
#pragma warning(pop)
#endif // _HAS_TR1_NAMESPACE

_STD_END

#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // RC_INVOKED
#endif // _TYPE_TRAITS_

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0009 */
